/**
* @file interface_spi.cpp
* @author Clemens Zangl
* @date 22.05.2012
* @version 0.1
*
* (c) 2012 University of Applied Sciences Karlsruhe
*
* Definition to interface_spi.h
** 
*/

#include "interfaces/spi/interface_spi.h"


using namespace HardwareInterface;


SPIInterface::SPIInterface(spiDevice device, spiConfiguration configuration)
	:_device(device), _configuration(configuration)
{
	if(deviceSPIOne == _device)
	{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);	//SPI_SLAVE_GPIO_CLK |
	}
	else if(deviceSPITwo == _device)
	{
		RCC_APB2PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);	//SPI_SLAVE_GPIO_CLK |
	}
	
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	
  GPIO_InitTypeDef GPIO_InitStructure;

	// configure SPI pins
	if(deviceSPIOne == _device)
	{
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
	}
	else if(deviceSPITwo == _device)
	{
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI2);
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI2);
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI2);
	}


	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
        
	
  /*!< SPI SCK pin configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /*!< SPI MOSI pin configuration */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /*!< SPI MISO pin configuration */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  SPI_InitTypeDef SPI_InitStructure;

  /* SPI configuration -------------------------------------------------------*/	
	if(configurationSPIMaster == getSPIConfiguration())
	{
		SPI_I2S_DeInit(getSPIDeviceID());
		SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
		SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
		SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
		SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
		SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
		SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
		SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
		SPI_InitStructure.SPI_CRCPolynomial = 7;
		SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
		SPI_Init(getSPIDeviceID(), &SPI_InitStructure);
	}
	else
	{
		/* SPI_SLAVE configuration -------------------------------------------------*/
		SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Rx;
		SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
		SPI_Init(getSPIDeviceID(), &SPI_InitStructure);
	}
	
  /* Enable SPI1  */
  SPI_Cmd(getSPIDeviceID(), ENABLE);
}


/**
Destructor.
TODO Clemens Implementation
*/
SPIInterface::~SPIInterface(void)
{
	
}


int SPIInterface::sendByte(unsigned char byte)
{
	SPI_I2S_SendData(getSPIDeviceID(), byte);
	return 0;
}



int SPIInterface::send(const unsigned char *buffer, size_t bufferSize)
{
	size_t i;
	for(i = 0; i != bufferSize; ++i)
	{
			sendByte(buffer[i]);
	}
	
	return 0;
}

int SPIInterface::readByte(unsigned char &result)
{
	result = (unsigned char)SPI_I2S_ReceiveData(getSPIDeviceID());
	return 0;
}

int SPIInterface::getFlagStatus(unsigned short flag, FlagStatus &status) const
{
	status = SPI_I2S_GetFlagStatus(getSPIDeviceID(), flag);
	return 0;
}

spiDevice SPIInterface::getSPIDevice(void) const
{
	return this->_device;
}


spiConfiguration SPIInterface::getSPIConfiguration(void) const 
{
	return this->_configuration;
}


SPI_TypeDef* SPIInterface::getSPIDeviceID(void) const
{
	if(deviceSPIOne == getSPIDevice())
	{
		return SPI1;
	}
	else
	{
			return SPI2;
	}	
}

